using UnityEngine;
using System.Collections;
using UnityEngine.EventSystems;
using LuaInterface;
using System.Collections.Generic;
public class EventListener : UnityEngine.EventSystems.EventTrigger
{
    public delegate void VoidDelegate(GameObject go);
    public LuaFunction onClick;
    public LuaFunction onDown;
    public LuaFunction onEnter;
    public LuaFunction onExit;
    public LuaFunction onUp;
    public LuaFunction onSelect;
    public LuaFunction onUpdateSelect;
    public LuaFunction onClickOnly;
    public LuaFunction onLongPress;
    public LuaFunction onPassClick;

    public float durationThreshold = 1.0f;

    private bool isPointerDown = false;
    private bool longPressTriggered = false;
    private float timePressStarted;

    public LuaFunction onDragBegin;
    public LuaFunction onDrag;
    public LuaFunction onDragEnd;

    public LuaFunction onPinch;
    public bool isDrag = false;

    private void Update()
    {
        if (isPointerDown && !longPressTriggered)
        {
            if (Time.time - timePressStarted > durationThreshold)
            {
                longPressTriggered = true;
                if (onLongPress != null) onLongPress.Call(durationThreshold);
            }
        }
    }

    private void OnDisable()
    {
        if (longPressTriggered)
        {
            if (onUp != null) onUp.Call();
        }
    }

    static public EventListener Get(GameObject go)
    {
        EventListener listener = go.GetComponent<EventListener>();
        if (listener == null) listener = go.AddComponent<EventListener>();
        return listener;
    }

    public static void AddClick(GameObject go, LuaFunction func)
    {
        EventListener listner = Get(go);
        listner.onClick = func;
    }

    public static void AddClickOnly(GameObject go, LuaFunction func)
    {
        EventListener listner = Get(go);
        listner.onClickOnly = func;
    }
    public static void AddPassClick(GameObject go, LuaFunction func)
    {
        EventListener listner = Get(go);
        listner.onPassClick = func;
    }

    public static void AddLongPress(GameObject go, LuaFunction func)
    {
        EventListener listner = Get(go);
        listner.onLongPress = func;
    }

    public static void AddDown(GameObject go, LuaFunction func)
    {
        EventListener listner = Get(go);
        listner.onDown = func;
    }

    public static void AddUp(GameObject go, LuaFunction func)
    {
        EventListener listner = Get(go);
        listner.onUp = func;
    }

    public static void AddEnter(GameObject go, LuaFunction func)
    {
        EventListener listner = Get(go);
        listner.onEnter = func;
    }

    public static void AddExit(GameObject go, LuaFunction func)
    {
        EventListener listner = Get(go);
        listner.onExit = func;
    }

    public static void AddSelect(GameObject go, LuaFunction func)
    {
        EventListener listner = Get(go);
        listner.onSelect = func;
    }

    public static void AddUpdateSelect(GameObject go, LuaFunction func)
    {
        EventListener listner = Get(go);
        listner.onUpdateSelect = func;
    }

    public static void AddClick(Transform go, LuaFunction func)
    {
        AddClick(go.gameObject, func);
    }
    public static void AddClickOnly(Transform go, LuaFunction func)
    {
        AddClickOnly(go.gameObject, func);
    }
    public static void AddPassClick(Transform go, LuaFunction func)
    {
        AddPassClick(go.gameObject, func);
    }
    public static void AddLongPress(Transform go, LuaFunction func)
    {
        AddLongPress(go.gameObject, func);
    }

    public static void AddDown(Transform go, LuaFunction func)
    {
        AddDown(go.gameObject, func);
    }

    public static void AddUp(Transform go, LuaFunction func)
    {
        AddUp(go.gameObject, func);
    }

    public static void AddEnter(Transform go, LuaFunction func)
    {
        AddEnter(go.gameObject, func);
    }

    public static void AddExit(Transform go, LuaFunction func)
    {
        AddExit(go.gameObject, func);
    }

    public static void AddSelect(Transform go, LuaFunction func)
    {
        AddSelect(go.gameObject, func);
    }

    public static void AddUpdateSelect(Transform go, LuaFunction func)
    {
        AddUpdateSelect(go.gameObject, func);
    }

    public static void AddDragBegin(GameObject go, LuaFunction func)
    {
        EventListener listner = Get(go);
        listner.onDragBegin = func;
    }

    public static void AddDragBegin(Transform go, LuaFunction func)
    {
        AddDragBegin(go.gameObject, func);
    }

    public static void AddDrag(GameObject go, LuaFunction func)
    {
        EventListener listner = Get(go);
        listner.onDrag = func;
    }

    public static void AddDrag(Transform go, LuaFunction func)
    {
        AddDrag(go.gameObject, func);
    }

    public static void AddDragEnd(GameObject go, LuaFunction func)
    {
        EventListener listner = Get(go);
        listner.onDragEnd = func;
    }

    public static void AddDragEnd(Transform go, LuaFunction func)
    {
        AddDragEnd(go.gameObject, func);
    }

    public override void OnPointerClick(PointerEventData eventData)
    {
        if (onClick != null && !isDrag)
        {
            onClick.Call(eventData);
        }
        if(onClickOnly != null)
        {
            onClickOnly.Call(eventData);
        }
        if (onPassClick != null)
        {
            List<RaycastResult> results = new List<RaycastResult>();
            EventSystem.current.RaycastAll(eventData, results);
            GameObject current = gameObject;
            bool succ = false;
            onPassClick.Call(eventData);
            for (int i = 0; i < results.Count; i++)
            {
               // Debug.Log(results[i].gameObject.name + " " + current.name);
                if (current != results[i].gameObject)
                {
                    if(ExecuteEvents.Execute(results[i].gameObject, eventData, ExecuteEvents.pointerClickHandler))
                    {
                        succ = true;
                    }
                    if (ExecuteEvents.Execute(results[i].gameObject, eventData, ExecuteEvents.pointerDownHandler))
                    {
                        succ = true;
                    }
                    if (succ) break;
                }
            }

        }
    }
    public override void OnPointerDown(PointerEventData eventData)
    {
        posDic[eventData.pointerId] = eventData.position;
        if (onDown != null)
        {
            onDown.Call(eventData);
        }
        isDrag = false;
        timePressStarted = Time.time;
        isPointerDown = true;
        longPressTriggered = false;
    }
    public override void OnPointerEnter(PointerEventData eventData)
    {
        if (onEnter != null) onEnter.Call(eventData);
    }
    public override void OnPointerExit(PointerEventData eventData)
    {
        if (onExit != null) onExit.Call(eventData);
        isPointerDown = false;
    }
    public override void OnPointerUp(PointerEventData eventData)
    {
        posDic.Remove(eventData.pointerId);
        if (onUp != null) onUp.Call(eventData);
        isPointerDown = false;
    }
    public override void OnSelect(BaseEventData eventData)
    {
        if (onSelect != null) onSelect.Call(eventData);
    }
    public override void OnUpdateSelected(BaseEventData eventData)
    {
        if (onUpdateSelect != null) onUpdateSelect.Call(eventData);
    }

    public override void OnBeginDrag(PointerEventData eventData)
    {
        if(onDragBegin != null)
        {
            onDragBegin.Call(eventData);
        }
        //PassEvent(eventData, ExecuteEvents.beginDragHandler);        
    }


    //把事件透下去
    public static void PassEvent<T>(PointerEventData data, ExecuteEvents.EventFunction<T> function)
        where T : IEventSystemHandler
    {
        return;//谨慎开启！
        List<RaycastResult> results = new List<RaycastResult>();
        EventSystem.current.RaycastAll(data, results);
        GameObject current = data.pointerCurrentRaycast.gameObject;
        for (int i = 0; i < results.Count; i++)
        {
            if (current != results[i].gameObject)
            {
                ExecuteEvents.Execute(results[i].gameObject, data, function);
                //RaycastAll后ugui会自己排序，如果你只想响应透下去的最近的一个响应，这里ExecuteEvents.Execute后直接break就行。
                break;
            }
        }
    }

    public static void PassBeginDragEvent(PointerEventData data)
    {
        PassEvent(data, ExecuteEvents.beginDragHandler);
    }

    public static void PassCancelEvent(PointerEventData data)
    {
        PassEvent(data, ExecuteEvents.cancelHandler);
    }

    public static void PassDeselectEvent(PointerEventData data)
    {
        PassEvent(data, ExecuteEvents.deselectHandler);
    }

    public static void PassDragEvent(PointerEventData data)
    {
        PassEvent(data, ExecuteEvents.dragHandler);
    }

    public static void PassDropEvent(PointerEventData data)
    {
        PassEvent(data, ExecuteEvents.dropHandler);
    }

    public static void PassEndDragEvent(PointerEventData data)
    {
        PassEvent(data, ExecuteEvents.endDragHandler);
    }

    public static void PassInitializePotentialEvent(PointerEventData data)
    {
        PassEvent(data, ExecuteEvents.initializePotentialDrag);
    }

    public static void PassMoveEvent(PointerEventData data)
    {
        PassEvent(data, ExecuteEvents.moveHandler);
    }

    public static void PassPointerClickEvent(PointerEventData data)
    {
        PassEvent(data, ExecuteEvents.pointerClickHandler);
    }

    public static void PassPointerDownEvent(PointerEventData data)
    {
        PassEvent(data, ExecuteEvents.pointerDownHandler);
    }

    public static void PassPointerEnterEvent(PointerEventData data)
    {
        PassEvent(data, ExecuteEvents.pointerEnterHandler);
    }

    public static void PassPointerExitEvent(PointerEventData data)
    {
        PassEvent(data, ExecuteEvents.pointerExitHandler);
    }

    public static void PassPointerUpEvent(PointerEventData data)
    {
        PassEvent(data, ExecuteEvents.pointerUpHandler);
    }

    public static void PassScrollEvent(PointerEventData data)
    {
        PassEvent(data, ExecuteEvents.scrollHandler);
    }

    public static void PassSelectEvent(PointerEventData data)
    {
        PassEvent(data, ExecuteEvents.selectHandler);
    }

    public static void PassSubmitEvent(PointerEventData data)
    {
        PassEvent(data, ExecuteEvents.submitHandler);
    }

    public static void PassUpdateSelectedEvent(PointerEventData data)
    {
        PassEvent(data, ExecuteEvents.updateSelectedHandler);
    }

    public static bool raycastUGUI(Vector3 pos, int layer)
    {
        PointerEventData pointer = new PointerEventData(EventSystem.current);
        pointer.position = pos;
        List<RaycastResult> list = new List<RaycastResult>();
        EventSystem.current.RaycastAll(pointer, list);

        if (list.Count == 0)
        {
            return false;
        }

        for(int i = 0; i < list.Count; i++)
        {
            if(list[i].gameObject.layer == layer)
            {
                return true;
            }
        }
        return false;
    }
    public static void AddPinch(Transform go, LuaFunction func)
    {
        AddPinch(go.gameObject, func);
    }

    public static void AddPinch(GameObject go, LuaFunction func)
    {
        EventListener listener = Get(go);
        listener.onPinch = func;
    }

    Dictionary<int, Vector2> posDic = new Dictionary<int, Vector2>();
    public override void OnDrag(PointerEventData eventData)
    {
        if (Input.touchCount >= 2)
        {
            Vector2[] oldPosArr = new Vector2[2];
            int Count = 0;
            Vector2[] nowPosArr = new Vector2[2];
            for (int i = 0; i < Input.touchCount; i++)
            {
                Touch touch = Input.GetTouch(i);
                Vector2 pos;
                bool flag = posDic.TryGetValue(touch.fingerId, out pos);
                if (flag)
                {
                    oldPosArr[Count] = pos;
                    nowPosArr[Count] = touch.position;
                    Count++;
                    if (Count == 2)
                    {
                        break;
                    }
                }
            }
            posDic[eventData.pointerId] = eventData.position;
            if (Count == 2)
            {
                float dis = zoomOff(oldPosArr[0], oldPosArr[1], nowPosArr[0], nowPosArr[1]);
                if (onPinch != null && Mathf.Abs(dis) > 0.1f)
                {
                    onPinch.Call(eventData, -dis * 0.012f);
                    return;
                }
            }

        }
        if (onDrag != null)
        {
            onDrag.Call(eventData);
        }
        isDrag = true;
        //PassEvent(eventData, ExecuteEvents.dragHandler);
    }

    float zoomOff(Vector2 oP1, Vector2 oP2, Vector2 nP1, Vector2 nP2)
    {
        float leng1 = Mathf.Sqrt((oP1.x - oP2.x) * (oP1.x - oP2.x) + (oP1.y - oP2.y) * (oP1.y - oP2.y));
        float leng2 = Mathf.Sqrt((nP1.x - nP2.x) * (nP1.x - nP2.x) + (nP1.y - nP2.y) * (nP1.y - nP2.y));
        return leng2 - leng1;
    }

    public override void OnEndDrag(PointerEventData eventData)
    {
        if(onDragEnd != null)
        {
            onDragEnd.Call(eventData);
        }
        //PassEvent(eventData, ExecuteEvents.endDragHandler);        
    }

//#if UNITY_EDITOR 
    [NoToLua]
    public override void OnScroll(PointerEventData eventData)
    {
        if(onPinch != null)
        {
            onPinch.Call(eventData, eventData.scrollDelta.y * 0.2f);
        }
    }
//#endif
}
